<script setup lang="ts">
import {
  Badge,
  ExtensionCategory,
  Graph,
  Label,
  Rect,
  RectStyleProps,
  RectStyleProps as GRectStyleProps,
  register
} from "@antv/g6";
import {deptApi} from "@/api/dept";
import {SysDept} from "@/api/dept/types.ts";
import type {Group} from "@antv/g";
import {useAppStore} from "@/stores";

const DEPT_NODE = 'dept-node';

type ParsedRectStyleProps = Required<RectStyleProps>;

const appStore = useAppStore();

class DeptNode extends Rect {

  get data() {
    return this.context.model.getElementDataById(this.id).data as SysDept;
  }

  protected getDeptNameStyle(): GRectStyleProps {
    const text = this.data.deptName
    return {
      text,
      fontSize: 16,
      fontWeight: 400,
      textAlign: 'left',
      transform: [['translate', -55, -8]],
      fill: '#63e2b7'
    }
  }

  protected getDeptLevelStyle(): GRectStyleProps {
    const text = String(this.data.deptLevel)
    return {
      text,
      fontSize: 8,
      fill: '#70c0e8',
      textAlign: 'left',
      transform: [['translate', 50, -11]],
      padding: [0, 4],
      backgroundFill: '#70c0e829'
    }
  }

  protected getDeptCodeStyle(): GRectStyleProps {
    return {
      text: this.data.deptCode,
      fontSize: 8,
      fontWeight: 400,
      textTransform: 'uppercase',
      textAlign: 'left',
      fill: '#D3d3d3',
      transform: [['translate', -55, 10]],
    }
  }

  protected getLeftValueStyle(): GRectStyleProps {
    const text = String(this.data.leftValue)
    return {
      text,
      fontSize: 8,
      fontWeight: 400,
      textAlign: 'left',
      fill: '#e0e0e0',
      transform: [['translate', -80, 0]],
    }
  }

  protected getRightValueStyle(): GRectStyleProps {
    const text = String(this.data.rightValue)
    return {
      text,
      fontSize: 8,
      fontWeight: 400,
      textAlign: 'right',
      fill: '#e0e0e0',
      transform: [['translate', 80, 0]],
    }
  }

  protected drawDeptNameShape(attributes: ParsedRectStyleProps, container: Group) {
    this.upsert('dept-name', Label, this.getDeptNameStyle(), container)
  }

  protected drawDeptCodeShape(attributes: ParsedRectStyleProps, container: Group) {
    this.upsert('dept-code', Label, this.getDeptCodeStyle(), container)
  }

  protected drawDeptLevelShape(attributes: ParsedRectStyleProps, container: Group) {
    this.upsert('dept-level', Badge, this.getDeptLevelStyle(), container)
  }

  protected drawLeftValueShape(attributes: ParsedRectStyleProps, container: Group) {
    this.upsert('left-value', Label, this.getLeftValueStyle(), container)
  }

  protected drawRightValueShape(attributes: ParsedRectStyleProps, container: Group) {
    this.upsert('right-value', Label, this.getRightValueStyle(), container)
  }

  render(attributes?: Required<RectStyleProps>, container?: Group) {
    super.render(attributes, container)
    this.drawDeptNameShape(attributes, container)
    this.drawDeptCodeShape(attributes, container)
    this.drawDeptLevelShape(attributes, container)
    this.drawLeftValueShape(attributes, container)
    this.drawRightValueShape(attributes, container)
  }
}

register(ExtensionCategory.NODE, DEPT_NODE, DeptNode)


onMounted(() => {
  deptApi.diagram().then(res => {
    const graph = new Graph({
      container: 'dept-diagram',
      data: res.data,
      node: {
        type: DEPT_NODE,
        style: {
          fill: appStore.darkTheme ? '#18181c' : '#fafafc',
          labelPlacement: 'center',
          lineWidth: 1,
          ports: [{placement: 'top'}, {placement: 'bottom'}],
          radius: 2,
          size: [135, 45],
          stroke: appStore.darkTheme ? '#ffffff17' : '#efeff5',
        },
      },
      edge: {
        type: 'polyline',
        style: {
          router: {
            type: 'orth',
          },
          stroke: appStore.darkTheme ? '#ffffff17' : '#efeff5',
        },
      },
      layout: {
        type: 'dagre',
      },
      autoFit: 'view',
      behaviors: ['zoom-canvas', 'drag-canvas'],
    });
    graph.render();
  })
})
</script>
<template>
  <div id="dept-diagram"/>
</template>
<style scoped>
</style>